const oracledb = require('oracledb');
const { cjporcl } = require('../lib/config_oracle');
const { dateFormat } = require('./dateFormat');
const net = require('net');

/**
 * 执行所有健康检查
 * @param {number} port 服务器端口
 */
const runAllHealthChecks = async (port = 3003) => {
    console.log(dateFormat(new Date()) + ' 开始执行服务启动前健康检查...');
    
    // 执行各项检查
    const portCheckResult = await checkPortAvailability(port);
    const dbCheckResult = await checkDatabaseConnection();
    
    // 汇总检查结果
    const allChecksPassed = portCheckResult.success && dbCheckResult.success;
    
    if (allChecksPassed) {
        console.log(dateFormat(new Date()) + ' 所有健康检查通过，可以启动服务器');
    } else {
        console.error(dateFormat(new Date()) + ' 健康检查未通过，服务器启动失败');
        console.error('详细检查结果:');
        console.error('端口检查:', portCheckResult);
        console.error('数据库检查:', dbCheckResult);
    }
    
    return {
        allChecksPassed,
        checks: {
            port: portCheckResult,
            database: dbCheckResult
        }
    };
};

// 内部函数实现--数据库连接检查
const checkDatabaseConnection = async () => {
    let connection;
    const checkResult = {
        success: false,
        message: '',
        time: dateFormat(new Date())
    };

    try {
        console.log(dateFormat(new Date()) + ' 开始数据库连接检查...');
        connection = await oracledb.getConnection(cjporcl);
        // 执行一个简单的查询来验证连接是否可用
        const result = await connection.execute('SELECT 1 FROM DUAL');
        
        if (result.rows && result.rows.length > 0) {
            checkResult.success = true;
            checkResult.message = '数据库连接成功';
            console.log(dateFormat(new Date()) + ' ' + checkResult.message);
        } else {
            checkResult.message = '数据库连接查询结果异常';
            console.error(dateFormat(new Date()) + ' ' + checkResult.message);
        }
    } catch (err) {
        checkResult.message = `数据库连接失败: ${err.message}`;
        console.error(dateFormat(new Date()) + ' ' + checkResult.message);
    } finally {
        if (connection) {
            try {
                await connection.close();
            } catch (err) {
                console.error(dateFormat(new Date()) + ' 关闭数据库连接时出错:', err);
            }
        }
    }
    
    return checkResult;
}

// 内部函数，供runAllHealthChecks使用--端口检查
const checkPortAvailability = async (port) => {
    return new Promise((resolve) => {
        const checkResult = {
            success: false,
            message: '',
            time: dateFormat(new Date())
        };
        
        const server = net.createServer();
        
        server.once('error', (err) => {
            if (err.code === 'EADDRINUSE') {
                checkResult.message = `端口 ${port} 已被占用`;
            } else {
                checkResult.message = `检查端口 ${port} 时出错: ${err.message}`;
            }
            console.error(dateFormat(new Date()) + ' ' + checkResult.message);
            resolve(checkResult);
        });
        
        server.once('listening', () => {
            server.close(() => {
                checkResult.success = true;
                checkResult.message = `端口 ${port} 可用`;
                console.log(dateFormat(new Date()) + ' ' + checkResult.message);
                resolve(checkResult);
            });
        });
        
        server.listen(port, 'localhost');
    });
}

module.exports = {
    checkDatabaseConnection,
    checkPortAvailability,
    runAllHealthChecks
};